/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.ofbiz.epos.print;

import java.io.File;
import java.io.IOException;
import java.util.Map;

import javax.print.PrintService;
import javax.print.PrintServiceLookup;

import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.UtilMisc;
import org.ofbiz.entity.Delegator;
import org.ofbiz.entity.util.EntityUtilProperties;
import org.ofbiz.service.DispatchContext;
import org.ofbiz.service.ServiceUtil;

/**
 * Print Services
 *
 */
public class PrintServices {

    public final static String module = PrintServices.class.getName();

    /*
     * print PDF file
     */
    public static Map<String, Object> printPdfFile(DispatchContext ctx, Map<String, ? extends Object> context) {
    	Delegator delegator = ctx.getDelegator();
        Map<String, Object> serviceContext = UtilMisc.makeMapWritable(context);
        String printerName = (String)serviceContext.remove("printerName");
        String filePath = (String)serviceContext.remove("filePath");
        
        try {
            if (filePath.charAt(0) != '/') {
                filePath = System.getProperty("user.dir") + "/" + filePath;
            }
            if (!printerExists(printerName)) {
                String errMsg = "Error while printing PDF: printer [" + printerName +"] not found";
                return ServiceUtil.returnError(errMsg);
            }
            printFile(printerName, filePath);
        }
        catch (InterruptedException ie) {
            String errMsg = "Error while printing PDF: " + ie.toString();
            Debug.logError(ie, errMsg, module);
            return ServiceUtil.returnError(errMsg);
        }
        catch (IOException ioe) {
            String errMsg = "Error while printing PDF: " + ioe.toString();
            Debug.logError(ioe, errMsg, module);
            return ServiceUtil.returnError(errMsg);
        }

        return ServiceUtil.returnSuccess();
    }

    public static String getDefaultPrinter(Delegator delegator) {
        return EntityUtilProperties.getPropertyValue("general", "DEFAULT_PRINTER", delegator);
    }

    public static boolean printerExists(String printerName) {
        PrintService[] printServices = PrintServiceLookup.lookupPrintServices(null, null);
        PrintService printService = null;

        for (PrintService printServiceEntry : printServices) {
            String sPrinterName = printServiceEntry.getName();
            if (sPrinterName.equals(printerName)) {
                printService = printServiceEntry;
            }
        }

        return printService != null;
    }

    public static boolean printFile(String printerName, String filePath) throws IOException, InterruptedException {
        if (!printerExists(printerName)) {
            Debug.logError(String.format("No printer found with name %s", printerName), module);
            return false;
        }

        File file = new File(filePath);
        if (!file.exists()) {
            Debug.logError(String.format("File %s not found", filePath), module);
            return false;
        }

        return printFileLP(printerName, filePath);
    }

    public static boolean printFile(String printerName, String filePath, Delegator delegator) throws IOException, InterruptedException {
    	if (printerName == null) {
        	printerName = getDefaultPrinter(delegator);
        }
        return printFile(printerName, filePath);
    }

    public synchronized static boolean printFileLP(String printerName, String filePath) throws IOException, InterruptedException {
        LPWrapper wrapper = new LPWrapper();

        wrapper.setPrinterName(printerName)
            .setInputFile(filePath);

        if (Debug.isOn(Debug.VERBOSE)) {
            Debug.logVerbose("Printing PDF file: [" + filePath+ "]. On printer: [" + printerName + "].", module);
            Debug.logVerbose(wrapper.toString(), module);
        }

        int result = wrapper.execute();

        if (result != 0 || Debug.isOn(Debug.VERBOSE)) {
            Debug.logInfo(String.format("StdOut: %s", wrapper.getStdOut()), module);
            Debug.logInfo(String.format("StdErr: %s", wrapper.getStdErr()), module);
        }

        return result == 0;
    }

}
